import string
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import os


# 验证码 颜色 干扰线 干扰点
class ImageVerifyUtil:
    def __init__(self, width=120, height=40, length=4, size=28):
        """
        初始化
        :param width:
        :param height:
        :param length: 验证码个数
        :param size: 字体大小
        """
        self.width = width
        self.height = height
        self.length = length
        self.size = size

    def random_str(self):
        """
        生成随机字符串
        :return:
        """
        sourse = string.ascii_letters + string.digits
        res = random.choices(sourse, k=self.length)  # 随机选择k个元素['','',]
        res_str = ''.join(res)
        return res_str

    def random_color(self, start=0, end=255):
        """
        rgb(0,0,0) rgb(255,255,255)
        :param start:
        :param end:
        :return: 颜色 (1,5,8) 元组
        """
        li = []
        for i in range(3):
            li.append(random.randint(start, end))
        return tuple(li)

    # 干扰线
    def random_lines(self, draw):
        """
        :param draw: 画笔
        :return:
        """
        # 起始点 结束点
        # li = []
        # for i in range(2):
        #     x = random.randint(0, self.width)  # x范围
        #     y = random.randint(0, self.height) # y范围
        #     li.append((x, y))  # [(x,y),(x,y)]
        # 干扰线数量
        for i in range(self.length):
            # 起始点 结束点 列表推导式 [(x,y),(x,y)]
            lines_xy = [(random.randint(0, self.width), random.randint(0, self.height)) for i in range(2)]
            # 绘制干扰线(坐标 颜色 线条粗细)
            draw.line(lines_xy, fill=self.random_color(0, 255), width=2)

    # 干扰点
    def random_points(self, draw):
        """
        :param draw: 画笔
        :return:
        """
        # 得到所有点坐标
        for x in range(self.width):
            for y in range(self.height):
                # 干扰点比例
                if random.randint(0, 100) <= 10:
                    # 绘制点
                    draw.point((x, y), fill=self.random_color(0, 255))

    # 整合验证码图片
    def verify_code(self):
        """
        画布 画笔
        :return: img code
        """
        # 生成画布
        img = Image.new('RGB', (self.width, self.height), (255, 255, 255))
        # 得到路径
        file = os.path.dirname(os.path.abspath(__file__))  # 当前文件路径 utils/
        # 指定字体路径
        font = ImageFont.truetype(f'{file}/HYYakuHei-85W.ttf', self.size)
        # 画 通过画布对象生成画笔
        draw = ImageDraw.Draw(img)
        # 返回
        self.random_lines(draw)
        self.random_points(draw)
        # 得到验证码
        code = self.random_str()  # k88l
        # 写入画布
        for i in range(self.length):
            draw.text((self.width / self.length * i, random.randint(-5, 5)), code[i], fill=self.random_color(),
                      font=font)
        # 画布模糊
        image = img.filter(ImageFilter.BLUR)
        # return image, code
        return img, code


if __name__ == '__main__':
    ivu = ImageVerifyUtil()
    # print(ivu.random_str())
    img, code = ivu.verify_code()
    with open('code.png', 'wb') as f:
        img.save(f)

    print(code)
